﻿namespace ufida.u9.ait.openapi
{
	using System;
    using System.Collections;
    using System.Collections.Generic;
	using System.Text;
    using ufida.u9.ait.openapi.utils;
    using UFIDA.U9.Base;
    using UFIDA.U9.Base.Organization;
    using UFIDA.U9.Base.UOM;
    using UFIDA.U9.Base.UserRole;
    using UFIDA.U9.CBO.Enums;
    using UFIDA.U9.CBO.HR.Operator;
    using UFIDA.U9.CBO.MFG.BOM;
    using UFIDA.U9.CBO.MFG.CostElement;
    using UFIDA.U9.CBO.MFG.Enums;
    using UFIDA.U9.CBO.SCM.Item;
    using UFIDA.U9.CBO.SCM.ProjectTask;
    using UFIDA.U9.ECN.ECN;
    using UFSoft.UBF.AopFrame;
    using UFSoft.UBF.Business;
    using UFSoft.UBF.Util.Context;

	/// <summary>
	/// ECNDocSaveSV partial 
	/// </summary>	
	public partial class ECNDocSaveSV 
	{	
		internal BaseStrategy Select()
		{
			return new ECNDocSaveSVImpementStrategy();	
		}		
	}
	
	#region  implement strategy	
	/// <summary>
	/// Impement Implement
	/// 
	/// </summary>	
	internal partial class ECNDocSaveSVImpementStrategy : BaseStrategy
	{
		public ECNDocSaveSVImpementStrategy() { }

		public override object Do(object obj)
		{						
			ECNDocSaveSV bpObj = (ECNDocSaveSV)obj;
            try
            {
				List<CopyOfCommonArchiveDataDTOData> retlist = new List<CopyOfCommonArchiveDataDTOData>();
                if (bpObj.Data==null||bpObj.Data.Count<=0)
                {
					throw new Exception("传入参数为空");
                }
				foreach(var dto in bpObj.Data)
                {
					ECNDoc entity = ECNDoc.Finder.Find($"DocNo='{dto.DocNo}'");
                    if (entity == null)
                    {
						//新增
						List<ECNBOMMaster> ecnboms = null;
						using (ISession session = Session.Open())
                        {
							entity = CreateHead(dto);
							CreateLine(entity, dto);
                            ecnboms = CreateECNBOM(entity, dto);
							session.Commit();
						}

						//BOM对比和变更
						using(ISession session = Session.Open())
                        {
							int i = 0;
							foreach(var ecnbom in ecnboms)
                            {
								//session.Commit()后,ecn bom的有效期会重置为当前日期
								//这里重置成单据申请日期
								//这样会导致不变的行也会变成修改,先注释了
								//ecnbom.EffectiveDate = DateTime.Parse(dto.ProposeDate);
								//foreach(var comp in ecnbom.ECNBOMComponents)
        //                        {
								//	comp.EffectiveDate = ecnbom.EffectiveDate;
        //                        }

								//BOM同步
                                ECNItemDetailAITDTOData linedto = dto.ECNItemDetails[i];
								ECNBOMSync(ecnbom, dto, linedto);
								i++;
                            }
							session.Commit();
                        }

						CopyOfCommonArchiveDataDTOData ret = new CopyOfCommonArchiveDataDTOData
						{
							ID = entity.ID,
							Code = entity.DocNo,
						};
						retlist.Add(ret);
					}
                    else
                    {
						//修改
						throw new AITException(599,$"单号[{dto.DocNo}]已经存在,不能生单");
                    }

				}

				return ResultUtils.success(bpObj, bpObj.Data, retlist);
            }catch(Exception ex)
            {
				return ResultUtils.error(bpObj, bpObj.Data, ex);
            }
		}

		//ECNBOM同传入数据对比(新增/修改/删除)
        private void ECNBOMSync(ECNBOMMaster master, ECNDocAITDTOData dto, ECNItemDetailAITDTOData linedto)
        {
			//更新BOM头属性
			//生效日期=单头:申请日期
			master.EffectiveDate = DateTime.Parse(dto.ProposeDate);
			//缓存ECNBOM
			Hashtable hashbom = new Hashtable();
			int seq = 0;
            foreach(var comp in master.ECNBOMComponents)
            {
				hashbom.Add(comp.ItemMaster.Code, comp);
                if (seq < comp.Sequence)
                {
					seq=comp.Sequence;
                }
            }
			//比对BOM表体,进行 新增/修改/删除操作
			foreach(var compdto in linedto.ECNBOMComponents)
            {
                if (hashbom.Contains(compdto.ItemMaster.Code))
                {
					//该子项在实体中存在
					ECNBOMComponent comp = (ECNBOMComponent)hashbom[compdto.ItemMaster.Code];
					if (IsDataChange(comp, compdto))
					{
						comp.UsageQty = compdto.UsageQty;
						comp.UsageQtyType = UsageQuantityTypeEnum.GetFromValue(compdto.UsageQtyType);
						comp.EffectiveDate = master.EffectiveDate;
						//                 if (!string.IsNullOrEmpty(compdto.DisableDate))
						//                 {
						//comp.DisableDate= DateTime.Parse(compdto.DisableDate);
						//                 }
						comp.ACDType = ACDTypeEnum.Change; //ECN状态为修改
					}
					hashbom.Remove(compdto.ItemMaster.Code);
                }
                else
                {
					//该子项不在实体中,则新增一行
					ECNBOMComponent comp = ECNBOMComponent.Create(master);
					comp.UsageQtyType = UsageQuantityTypeEnum.GetFromValue(compdto.UsageQtyType);
					comp.UsageQty = compdto.UsageQty;
					comp.TimeUOM = EntityUtils.GetEntityByCode<UOM>("Day");
					ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(compdto.ItemMaster?.Code);
					comp.SupplyWh = item.InventoryInfo.Warehouse;
					seq += 10;
					comp.Sequence = seq;
					comp.Priority = compdto.Priority;
					comp.ParentQty = compdto.ParentQty;
					comp.OperationNum = compdto.OperationNum;
					comp.MinSelectedQty = compdto.MinSelectedQty;
					comp.MaxSelectedQty = compdto.MaxSelectedQty;
					comp.IUTOIAURate = 1;
					comp.ItemMaster = item;
					comp.IssueUOM = item.MaterialOutUOM;
					comp.IssueAssistantUOM = item.MaterialOutUOM.BaseUOM;
					comp.IssueOrg = EntityUtils.GetEntityByCode<Organization>(compdto.IssueOrg?.Code);
					comp.IsIssueOrgFixed = compdto.IsIssueOrgFixed;
					comp.IsEffective = true;
					comp.IsDefault = true;
					comp.IsCharge = true;
					comp.IsCalcPrice = true;
					//生效日期
					comp.EffectiveDate = master.EffectiveDate;
					comp.DisableDate = DateTime.Parse(compdto.DisableDate ?? DateTime.MaxValue.ToString());
					comp.CostElement = CostElement.Finder.FindByID(item.MfgInfo.CostElement);
					comp.ConsignProcessItemSrc = ConsignProcessItemSrcEnum.GetFromValue(compdto.ConsignProcessItemSrc);
					comp.SubcontractItemSrc = SubContractItemSrcEnum.Empty;
					comp.ACDType = ACDTypeEnum.Add; //ECN状态为新增

					comp.CompProject = EntityUtils.GetEntityByCode<Project>(compdto.Project);
				}
            }

			//原BOM多出部分,作废掉
			foreach(var key in hashbom.Keys)
            {
				ECNBOMComponent comp = (ECNBOMComponent)hashbom[key];
				comp.ACDType = ACDTypeEnum.Disable;
			}
        }
		//对比BOM表体是否变化
		private bool IsDataChange(ECNBOMComponent comp, ECNBomComponentAITDTOData compdto)
        {
			if (comp.ItemMaster.Code != compdto.ItemMaster.Code)
				return true;
			if (comp.UsageQty != compdto.UsageQty)
				return true;
			if (comp.UsageQtyType.Value != compdto.UsageQtyType)
				return true;
			//if (!string.IsNullOrEmpty(compdto.EffectiveDate) && comp.EffectiveDate != DateTime.Parse(compdto.EffectiveDate))
			//	return true;
			//if (!string.IsNullOrEmpty(compdto.DisableDate) && comp.DisableDate != DateTime.Parse(compdto.DisableDate))
			//	return true;
			return false;
        }

		//构造ECN的BOM明细数据
        private List<ECNBOMMaster> CreateECNBOM(ECNDoc entity, ECNDocAITDTOData dto)
        {
			List<ECNBOMMaster> retlist = new List<ECNBOMMaster>();

			foreach (var line in entity.ECNItemDetails)
            {
				ECNBOMMaster master = ECNBOMMaster.Create();
				User user = User.Finder.FindByID(Context.LoginUserID);
				master.StatusUser = user;
				BOMMaster bom = line.ChangeBOM;
				master.StatusTime = bom.CreatedOn;
				master.PUTOPAURate = 1;
				master.ProductUOM = bom.ItemMaster.ManufactureUOM;
				master.ProductAssistantUOM = bom.ItemMaster.ManufactureUOM.BaseUOM;
				master.Org = bom.Org;
				master.OperationYield = bom.OperationYield;
				master.Lot = bom.Lot;
				master.ItemMaster = bom.ItemMaster;
				master.EffectiveDate=DateTime.Now;
				master.DisableDate = DateTime.MaxValue;
				master.ECNItemDetail = line;
				master.BOMVersionCode = line.Version;
				master.ACDType= line.ACDType;
				master.Project = bom.Project;
				master.IsPrimaryLot = true;//主批量
				master.IsCostRoll = true;//成本卷积默认

				foreach(var comp in bom.BOMComponents)
                {
					ECNBOMComponent ecncomp = ECNBOMComponent.Create(master);
					ecncomp.UsageQtyType=comp.UsageQtyType;
					ecncomp.UsageQty=comp.UsageQty;
					ecncomp.TimeUOM=comp.TimeUOM;
					ecncomp.SupplyWh = comp.SupplyWareHouse;
					ecncomp.Sequence=comp.Sequence;
					ecncomp.Priority=comp.Priority;
					ecncomp.ParentQty=comp.ParentQty;
					ecncomp.OriginalID = comp.ID;
					ecncomp.OperationNum=comp.OperationNum;
					ecncomp.MinSelectedQty=comp.MinSelectedQty;
					ecncomp.MaxSelectedQty=comp.MaxSelectedQty;
					ecncomp.IUTOIAURate=comp.IUTOIAURate;
					ecncomp.ItemMaster=comp.ItemMaster;
					ecncomp.IssueUOM=comp.IssueUOM;
					ecncomp.IssueOrg=comp.IssueOrg;
					ecncomp.IssueAssistantUOM=comp.IssueAssistantUOM;
					ecncomp.IsIssueOrgFixed=comp.IsIssueOrgFixed;
					ecncomp.IsDefault=comp.IsDefault;
					ecncomp.IsCharge=comp.IsCharge;

					ecncomp.IsEffective = comp.IsEffective;
					ecncomp.EffectiveDate=comp.EffectiveDate;
					ecncomp.DisableDate=comp.DisableDate;

					ecncomp.CostElement=comp.CostElement;
					ecncomp.CopyFromBOM = true;
					ecncomp.ConsignProcessItemSrc=comp.ConsignProcessItemSrc;
					ecncomp.CompGUID=comp.CompGUID;
					ecncomp.SubcontractItemSrc = SubContractItemSrcEnum.Empty;
					ecncomp.ACDType = ACDTypeEnum.UnChange;
					ecncomp.CompProject=comp.CompProject;
				}

				retlist.Add(master);
			}
			return retlist;

        }
		//构造ECN行数据
        private void CreateLine(ECNDoc doc, ECNDocAITDTOData dto)
        {
			int i = 0;
            foreach(var linedto in dto.ECNItemDetails)
            {
				i++;
				ECNItemDetail line = ECNItemDetail.Create(doc);
				string opath = $"ItemMaster.Code='{linedto.ItemMaster.Code}' and AlternateType={linedto.AlternateType} and BOMType={linedto.BOMType} and BOMVersionCode='{linedto.OriginalVersion}'";
				BOMMaster master = BOMMaster.Finder.Find(opath);
				if(master == null)
                {
					throw new Exception($"查找BOM失败,opath:[{opath}]");
                }
				line.ChangeBOM = master;
				line.ChgObjCode = master.ItemMaster.Code + "/" + master.BOMVersionCode;
				line.ChgObjName=master.ItemMaster.Name+"/"+master.BOMVersionCode;
				line.ACDType = ACDTypeEnum.GetFromValue(linedto.ACDType);
				line.ProductUOM = master.ItemMaster.ManufactureUOM;
				line.ItemMaster = master.ItemMaster;
				line.IsConsiderMRP = true;
				line.LineNum = i;
				line.Lot=linedto.Lot;
				line.OriginalDisableDate = master.DisableDate;
				line.PlanReleaseDate=DateTime.Now;
				line.OriginalVersion = master.BOMVersionCode;
				line.Version = linedto.Version;
				line.Project = EntityUtils.GetEntityByCode<Project>(linedto.Project);

			}
        }
		//构造ECN头数据
        private ECNDoc CreateHead(ECNDocAITDTOData dto)
        {
			ECNDoc doc = ECNDoc.Create();
			doc.WorkFlowID = Guid.Empty;
			doc.StateMachineID= Guid.Empty;

			doc.DocNo = dto.DocNo;
			doc.Proposer = EntityUtils.GetEntityByCode<Operators>(dto.Proposer?.Code);
			doc.Department = doc.Proposer.Dept;
			doc.ProposeDate = DateTime.Parse(dto.ProposeDate);
			doc.BusinessDate = doc.ProposeDate;
			doc.Org=EntityUtils.GetEntityByCode<Organization>(dto.Org?.Code);
			doc.IsAddNewVersion = dto.IsAddNewVersion;
			doc.ECNDocType=EntityUtils.GetEntityByCode<ECNDocType>(dto.ECNDocType?.Code);
			doc.ChangeType=EntityUtils.GetEntityByCode<ECNType>(dto.ChangeType?.Code);
			doc.ChangeReason=EntityUtils.GetEntityByCode<ECNReason>(dto.ChangeReason?.Code);
			
			return doc;
        }
    }

	#endregion
	
	
}